
#include "pcre_rml.h"
#include "internal.h"


pcre* compile_prce (const char* pattern, const vector<BYTE>& table)
{
	int erroffset;
	const char *error;
	pcre *re = pcre_compile(pattern,
						0,                    /* default options */
						&error,               /* for error message */
						&erroffset,           /* for error offset */
						&table[0]
						);                /* use default character tables */
	

	if (re == NULL)
	{
		ErrorMessage (Format("cannot parse regular expression \"%s\" offset=%i, error=%s",pattern, erroffset, error));
		return 0;
	}
	return re;
};

bool has_regular_expression (const pcre* re, const char* subject, size_t subject_len)
{
	const int OVECCOUNT = 30;    /* should be a multiple of 3 */
	int ovector[OVECCOUNT];
	int rc = pcre_exec(re,NULL,                 
				subject,              /* the subject string */
				subject_len,       /* the length of the subject */
				0,                    /* start at offset 0 in the subject */
				0,                    /* default options */
				ovector,              /* output vector for substring information */
				OVECCOUNT);           /* number of elements in the output vector */

	return rc >= 0;
};

void RmlPcreMakeTables(vector<BYTE>& table, MorphLanguageEnum Langua)
{
	table.resize(tables_length);
	int start  = 0;
	/* First comes the lower casing table */
	for (size_t i = 0; i < 256; i++) 
		if (is_upper_alpha(i, Langua))
			table[i+start] = ReverseChar(i, Langua);

	start = 256;
	/* Next the case-flipping table */
	for (size_t i = 0; i < 256; i++) 
		table[i+start] = ReverseChar(i, Langua);

	start += 256;
	for (size_t i=0; i < cbit_length; i++)
		table[i+start] = 0;
	
	for (size_t i = 0; i < 256; i++)
	{
		if (isdigit(i))
		{
			table[start+cbit_digit  + i/8] |= 1 << (i&7);
			table[start+cbit_word   + i/8] |= 1 << (i&7);
		}

		if (is_upper_alpha(i, Langua))
		{
			table[start+cbit_upper  + i/8] |= 1 << (i&7);
			table[start+cbit_word   + i/8] |= 1 << (i&7);
		}

		if (is_lower_alpha(i, Langua))
		{
			table[start+cbit_lower  + i/8] |= 1 << (i&7);
			table[start+cbit_word   + i/8] |= 1 << (i&7);
		}
		if (i == '_')   table[start+cbit_word   + i/8] |= 1 << (i&7);
		if (isspace(i)) table[start+cbit_space  + i/8] |= 1 << (i&7);
		if (isxdigit(i))table[start+cbit_xdigit + i/8] |= 1 << (i&7);
		if (is_alpha(i, Langua) ||ispunct(i)) table[start+cbit_graph  + i/8] |= 1 << (i&7);
		if (is_alpha(i, Langua) ||isprint(i)) table[start+cbit_print  + i/8] |= 1 << (i&7);
		if (ispunct(i)) table[start+cbit_punct  + i/8] |= 1 << (i&7);
		if (iscntrl(i)) table[start+cbit_cntrl  + i/8] |= 1 << (i&7);
	}

	start += cbit_length;

/* Finally, the character type table. In this, we exclude VT from the white
space chars, because Perl doesn't recognize it as such for \s and for comments
within regexes. */

	for (size_t i = 0; i < 256; i++)
	{
		int x = 0;
		if (i != 0x0b && isspace(i)) x += ctype_space;
		if (isalpha(i)) x += ctype_letter;
		if (isdigit(i)) x += ctype_digit;
		if (isxdigit(i)) x += ctype_xdigit;
		if (isalnum(i) || i == '_') x += ctype_word;

		/* Note: strchr includes the terminating zero in the characters it considers.
		In this instance, that is ok because we want binary zero to be flagged as a
		meta-character, which in this sense is any character that terminates a run
		of data characters. */

		if (strchr("*+?{^.$|()[", i) != 0) 
			x += ctype_meta; 

		table[start+i] = x; 
	}

}
